/*
   setaffin_not.c
   
   Do not distribute a process-bound computation over all processors
  
   Use it like this:   prompt> time setaffin_not
*/
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

/*   
     The following structure contains the necessary information  
     to allow the function "dotprod" to access its input data and 
     place its output so that it can be accessed later. 
*/
typedef struct {
   double *a;
   double *b;
   double sum; 
   int veclen; 
} DOTDATA;

#define VECLEN 100000
DOTDATA dotstr; 

/*
  We will use a function (dotprod) to perform the scalar product. 
  All input to this routine is obtained through a structure of 
  type DOTDATA and all output from this function is written into
  this same structure.  While this is unnecessarily restrictive 
  for a sequential program, it will turn out to be useful when
  we modify the program to compute in parallel.
*/
void *dotprod(void *data) {

   /* Define and use local variables for convenience */
   int start, end, i, j; 
   double mysum, *x, *y;
	
   /*   unsigned long mask = 1; */  /* select one processor */
   unsigned long mask = 15; /* select all processors */
	/*
   if (pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask) < 0) {
      perror("pthread_setaffinity_np");
   }
	*/

   start=0;
   end = dotstr.veclen;
   x = dotstr.a;   /* one vector */
   y = dotstr.b;   /* second vector */

   /*
     Perform the dot product and assign result
     to the appropriate variable in the structure. 
   */
   for (j=0 ; j < 2000 ; j++) {
      mysum = 0;
      for (i=start ; i < end ; i++) mysum += (x[i] * y[i]);
      dotstr.sum = mysum;
   }
}

/*
  The main program initializes data and calls the dotprd() function.
  Finally, it prints the result.
*/

int main (int argc, char *argv[]) {
   pthread_t p;
   pthread_attr_t attr;
   int i, len, stacksize;
   double *a, *b;
   void *status;

   /* Assign storage and initialize values */
   len = VECLEN;
   a = (double*) malloc(len*sizeof(double));
   b = (double*) malloc(len*sizeof(double));
   
   for (i=0 ; i < len ; i++) a[i] = b[i] = 1;

   dotstr.veclen = len; 
   dotstr.a = a; 
   dotstr.b = b; 
   dotstr.sum=0;

   /* Perform the  dotproduct */
   pthread_attr_init(&attr);
   stacksize = 50000000;
   pthread_attr_setstacksize (&attr, stacksize);
   pthread_create(&p, &attr, dotprod, NULL);
   pthread_join(p, &status);

   /* Print result and release storage */ 
   printf ("Sum =  %f \n", dotstr.sum);
   free (a);
   free (b);
}
